'use client';

import './style.scss';
import { usePathname, useSearchParams } from 'next/navigation';
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { BoardLayout, BoardSort, PostSearchType } from '@/constants/forum';
import { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { fetchApi } from '@/lib/utils/client';
import useErrorAlert from '@/hooks/useErrorAlert';
import Loading from '@/app/component/Loading';
import Pagination from '@/app/component/Pagination';
import { BoardResponse, BoardPostsResponse } from '@/types/response/forum/board';
import Post from '@/types/forum/post';
import useDragScroll from '@/hooks/useDragScroll';
import PostWriteButton from '../_component/PostWriteButton';
import NavTab from '@/app/(main)/support/navTab';
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import HeaderContent from '../_component/HeaderContent';
import FooterContent from '../_component/FooterContent';
import DefaultListLayout from '../_component/DefaultListLayout';
import AlbumListLayout from '../_component/AlbumListLayout';
import QnAListLayout from '../_component/QnAListLayout';

type ViewProps = {
	_query: {
		page: number;
		perPage: number;
		prefix?: number;
		sort?: BoardSort;
		search: PostSearchType;
		keyword?: string;
	},
	_board: BoardResponse,
	_postList: BoardPostsResponse
};

export default function View({ _query, _board, _postList }: ViewProps)
{
	const pathname = usePathname();
	const searchParams = useSearchParams();
	const { setError } = useErrorAlert();
	const [loading, setLoading] = useState<boolean>(false);
	const [total, setTotal] = useState<number>(_postList.total);
	const [speaker, setSpeaker] = useState<Post[]>(_postList.speaker);
	const [notice, setNotice] = useState<Post[]>(_postList.notice);
	const [list, setList] = useState<Post[]>(_postList.list);
	const [page, setPage] = useState<number>(_query.page);
	const [perPage, setPerPage] = useState<number>(_query.perPage);
	const [boardPrefixID, setBoardPrefixID] = useState<number|undefined>(_query.prefix);
	const [sort, setSort] = useState<BoardSort|undefined>(_query.sort);
	const [search, setSearch] = useState<PostSearchType>(_query.search);
	const [keyword, setKeyword] = useState<string|undefined>(_query.keyword);
	const [params, setParams] = useState<Record<string, string>>({});
	const [searchDialogOpen, setSearchDialogOpen] = useState(false);
	const isMounted = useRef(false);
	const searchRef = useRef(search);
	const keywordRef = useRef(keyword);
	const dragScroll = useDragScroll<HTMLElement>();
	searchRef.current = search;
	keywordRef.current = keyword;
	const startIndex = useMemo(() => total - ((page - 1) * perPage), [total, page, perPage]);

	// 상태 => URL 동기화
	useEffect(() => {
		// 기존 URL 파라미터
		const alreadyParams = new URLSearchParams(searchParams.toString());

		// URL 파라미터 덮어쓰기 및 삭제
		Object.entries(params).forEach(([k, v]) => {
			if (v) {
				alreadyParams.set(k, v);
			} else {
				alreadyParams.delete(k);
			}
		});

		const queryString = `?${alreadyParams.toString()}`;
		if (window.location.search !== queryString) {
			window.history.replaceState(null, '', `${pathname}${queryString}`);
		}

	}, [page, perPage, boardPrefixID, sort, search, keyword, params, pathname, searchParams]);

	const handleFetchPosts = useCallback(async () => {
		try {
			setLoading(true);

			const queryParams = new URLSearchParams();

			queryParams.set('boardID', String(_board.id));
			queryParams.set('page', String(page));
			queryParams.set('perPage', String(perPage));

			if (boardPrefixID) {
				queryParams.set('boardPrefixID', String(boardPrefixID));
			}
			if (sort !== undefined && sort !== null) {
				queryParams.set('sort', String(sort));
			}
			if (searchRef.current !== undefined && searchRef.current !== null) {
				queryParams.set('search', String(searchRef.current));
			}
			if (keywordRef.current) {
				queryParams.set('keyword', keywordRef.current);
			}

			const res = await fetchApi<BoardPostsResponse>(`/api/forum/posts?${queryParams.toString()}`);

			if (!res.data) {
				setError('게시글을 불러올 수 없습니다.');
			} else {
				setTotal(res.data.total);
				setSpeaker(res.data.speaker);
				setNotice(res.data.notice);
				setList(res.data.list);
			}
		} catch (err) {
			if (err instanceof Error) {
				setError(err.message || '알 수 없는 오류가 발생했습니다.');
			}
		} finally {
			setLoading(false);
		}
	}, [_board.id, boardPrefixID, page, perPage, sort]);

	const handlePageChange = useCallback((page: number) => {
		setPage(page);
		setParams((prev) => ({ ...prev, page: String(page) }));
	}, []);

	const handleChange = useCallback((e: React.ChangeEvent<HTMLSelectElement|HTMLInputElement>) => {
		const { name, value } = e.target;

		let key = '';
		switch (name) {
			case 'boardPrefixID':
				setBoardPrefixID((Number(value) || undefined) as number);
				key = 'prefix';
				break;
			case 'sort':
				setSort(Number(value) as BoardSort);
				break;
			case 'perPage':
				setPerPage(Number(value));
				break;
			case 'search':
				setSearch(Number(value) as PostSearchType);
				break;
			case 'keyword':
				setKeyword(value);
				break;
		}

		if (['sort', 'perPage', 'search', 'keyword'].includes(name)) {
			key = name;
		}

		if (['boardPrefixID', 'perPage', 'search', 'keyword'].includes(name)) {
			handlePageChange(1);
		}

		setParams((prev) => ({ ...prev, [key]: value }));
	}, [handlePageChange]);

	const handleSearch = useCallback((e: React.FormEvent) => {
		e.preventDefault();
		handleFetchPosts();
	}, [handleFetchPosts]);

	const handleSearchDialog = useCallback((e: React.FormEvent) => {
		e.preventDefault();
		handleFetchPosts();
		setSearchDialogOpen(false);
	}, [handleFetchPosts]);

	useEffect(() => {
		if (!isMounted.current) {
			isMounted.current = true;
			return;
		}

		handleFetchPosts();
	}, [page, perPage, boardPrefixID, sort, handleFetchPosts]);

	return (
		<>
		{_board.code === 'notice' && <NavTab currentTab='notice' />}
		<div id='board'>
			{loading && <Loading />}

			<HeaderContent isEnabled={_board.boardMeta.list.showHeader} content={_board.boardMeta.list.headerContent } />

			<div className='list-header'>
				{/* 말머리 */}
				<section aria-label='말머리 선택'>
					<h1>{ _board.name }</h1>
					<article ref={dragScroll.ref} onMouseDown={dragScroll.onMouseDown} onMouseMove={dragScroll.onMouseMove} onMouseUp={dragScroll.onMouseUp} onMouseLeave={dragScroll.onMouseLeave}>
						<ul>
							<li>
								<label {...(!boardPrefixID ? { className: 'active' } : {})}>
									<input type='radio' name='boardPrefixID' value='' checked={boardPrefixID === null} onChange={handleChange} /> 전체
								</label>
							</li>
							{_board.boardPrefix.map((row, i) => (
								<li key={i}>
									<label {...(boardPrefixID === row.id ? { className: 'active' } : {})}
										style={row.color && row.color !== '#000000' ? { background: row.color, color: '#f1f1f1' } : undefined}
									>
										<input type='radio' name='boardPrefixID' value={row.id} checked={boardPrefixID === row.id} onChange={handleChange}/>
										{row.name}
									</label>
								</li>
							))}
						</ul>
					</article>
				</section>

				{/* 정렬 */}
				<section aria-label='게시글 정렬'>
					<select name='sort' value={sort ?? ''} title='게시글 정렬' onChange={handleChange}>
						<option value={BoardSort.CreatedAt}>최신순</option>
						<option value={BoardSort.Views}>조회순</option>
						<option value={BoardSort.Comments}>댓글순</option>
						<option value={BoardSort.Likes}>공감순</option>
					</select>
				</section>

				{/* 출력 수 */}
				<section aria-label='게시글 출력 수'>
					<select name='perPage' value={perPage} title='출력 수' onChange={handleChange}>
						<option value='10'>10개씩</option>
						<option value='20'>20개씩</option>
						<option value='30'>30개씩</option>
						<option value='50'>50개씩</option>
						<option value='100'>100개씩</option>
					</select>
				</section>
			</div>

			{/* 게시글 목록 */}
			{(() => {
				switch (_board.boardMeta.list.layout) {
					case BoardLayout.Media:
						return <AlbumListLayout boardListMeta={_board.boardMeta.list} speaker={speaker} notice={notice} list={list} startIndex={startIndex} onChange={setBoardPrefixID} />;
					case BoardLayout.QnA:
						return <QnAListLayout boardListMeta={_board.boardMeta.list} notice={notice} list={list} startIndex={startIndex} onChange={setBoardPrefixID} />;
					default:
						return <DefaultListLayout boardListMeta={_board.boardMeta.list} speaker={speaker} notice={notice} list={list} startIndex={startIndex} onChange={setBoardPrefixID} />;
				}
            })()}

			{/* 검색 */}
			<div className='list-footer'>
				{/* 모바일: 검색 아이콘 → Dialog */}
				<Dialog open={searchDialogOpen} onOpenChange={setSearchDialogOpen}>
					<DialogTrigger asChild>
						<button type='button' className='btn btn-default search-toggle' title='검색'>
							<FontAwesomeIcon icon={faMagnifyingGlass}/>
						</button>
					</DialogTrigger>
					<DialogContent className='w-[90%] sm:max-w-md'>
						<DialogHeader>
							<DialogTitle>게시글 검색</DialogTitle>
						</DialogHeader>
						<form onSubmit={handleSearchDialog} autoComplete='off' className='flex flex-col gap-3'>
							<select name='search' value={search ?? ''} title='검색 구분' onChange={handleChange} className='h-9 rounded-md border px-3'>
								<option value={PostSearchType.Subject}>제목</option>
								<option value={PostSearchType.Content}>내용</option>
								<option value={PostSearchType.Author}>작성자</option>
								<option value={PostSearchType.Comment}>댓글</option>
							</select>
							<input type='text' name='keyword' value={keyword} placeholder='검색어를 입력해주세요.' onChange={handleChange} className='h-9 rounded-md border px-3' />
							<button type='submit' className='btn btn-default w-full'>검색</button>
						</form>
					</DialogContent>
				</Dialog>

				{/* 데스크톱: 인라인 검색 폼 */}
				<section aria-label='게시글 검색'>
					<form onSubmit={handleSearch} autoComplete='off'>
						<select name='search' value={search ?? ''} title='검색 구분' onChange={handleChange}>
							<option value={PostSearchType.Subject}>제목</option>
							<option value={PostSearchType.Content}>내용</option>
							<option value={PostSearchType.Author}>작성자</option>
							<option value={PostSearchType.Comment}>댓글</option>
						</select>
						<input type='text' name='keyword' value={keyword} placeholder='검색어를 입력해주세요.' onChange={handleChange} />
						<button type='submit' className='btn btn-default'>검색</button>
					</form>
				</section>

				{/* 글쓰기 버튼 */}
				<PostWriteButton alwaysShowButton={_board.boardMeta.list.alwaysShowWriteButton} boardCode={_board.code} boardMeta={_board.boardMeta} boardManagers={_board.boardManager} />
			</div>

			<Pagination total={total} page={page} perPage={perPage} onChange={handlePageChange} />

			<FooterContent isEnabled={_board.boardMeta.list.showFooter} content={_board.boardMeta.list.footerContent } />
		</div>
		</>
	);
}